package dw2;

import java.awt.*;
import java.util.Random;
import java.util.ArrayList;

public class Worm
{
    public Main parent;
    private int hp;
    private double shakemargin = 45;
    private int max_hp;

    private Image worm_head_img;
    private Image worm_seg_img;
    public ArrayList<Worm_Segment> segments;


    private int combo_points;
    public boolean comboMode = false;
    public String comboModeS = "false";
    public boolean showComboText = false;
    private int killCount = 0;
    private int comboKills = 0;
    private int comboCount = 0;
    private double multiplier = 1.0;
    public ComboManager comboManager;

    
    private double speedMax = 10;
    private double speedMin = 5;
    private double friction = .25;
    private double acceleration = .25;
    private double gravity = 1;
    private double turn = 5;
    private double slowturn = 3;
    private double distance = 30;
    private boolean aboveGround = false;


    private int segmentCount = 8; // 25;
    private int score;
    private int segmentSpacing = 30;

    Random random;
    private boolean hit = false;

    public Worm(Image head_img,Image body_img, Main parent)
    {
        worm_head_img = head_img;
        worm_seg_img = body_img;
        this.parent = parent;
        random = new Random();
        segments =  new ArrayList<Worm_Segment>();
        comboManager = new ComboManager(this);
        reset_worm();

    }

    public int getScore()
    {
        return score;
    }
    public void countKill()
    {
        killCount++;
        if(comboMode) comboKills++;
        if(comboMode && aboveGround) {
            comboCount++;
        }
        checkKills();
    }
    public void checkKills() {
        if(comboMode){
            if(comboCount == 1) {
                comboManager.run(comboCount);
            }
            if(comboKills == 4) {
                comboModeS = "false";
                toggleComboMode();
                comboManager.run(comboCount);
                comboCount = 0;
                comboKills = 0;
            }
        }
    }
    public void add_points(int value)
    {
        score += value * multiplier;

    }
    public void reset_worm()
    {
        int loc_x = 500, loc_y = 128;
        max_hp = hp = 100;
        combo_points = 0;
        score = 0;
        segments.clear();
        for(int w = 0;w<segmentCount;w++)
        {
            if(w == 0)
                segments.add( new Worm_Segment(worm_head_img,loc_x,loc_y));
            else
                segments.add( new Worm_Segment(worm_seg_img,loc_x,loc_y));
            loc_x -= segmentSpacing;
        }
    }
    public int getHP()
    {
        return hp;
    }
    public void toggleComboMode()
    {
        comboMode = !comboMode;
    }
    public boolean getComboMode()
    {
        return comboMode;
    }
    public int getMaxHP()
    {
        return max_hp;
    }
    public void hurtWorm(int damage)
    {
        hp -= damage;
        if(hp > 100){
            hp = 100;
        }
    }

    public Point getHeadPosition()
    {
        return new Point(segments.get(0).x,segments.get(0).y);
    }


    public static double getXspeed(double direction, double speed)
    {
        return Math.cos(Math.toRadians(direction))*speed;
    }

    public static double getYspeed(double direction, double speed)
    {
        return Math.sin(Math.toRadians(direction))*speed;
    }


    //need to change the name cause the worm would be using this
    public static double calcYspeed(double y2,double x_speed)
    {
        double x2 = x_speed;
        int x1 = 0, y1 = 0;
        double H = Math.sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1)); // The hypotenuse
        double x = x2-x1; // The opposite
        double y = y2-y1; // The adjacent
        double angle = Math.acos(x/H);
        angle = angle * 57.2960285258;
        if(y < 0)
        {
            angle = 360-angle;
        }
        return angle;
    }

    public static double getSpeed(double xspeed, double yspeed)
    {
    	return Math.sqrt((xspeed)*(xspeed) + (yspeed)*(yspeed));
    }


    //Situations where you only care if you hit the Worm's head
    public boolean hitHead(Rectangle bounds)
    {
        return segments.get(0).getBounds().intersects(bounds);
    }

    //Situation when you want to know if you hit the Worm
    public boolean hitWorm(Rectangle bounds)
    {
        for(int x = 0;x<segments.size();x++)
        {
            if(segments.get(x).getBounds().intersects(bounds)==true){                
               return true;
            }
        }
        return false;
    }

    public static double pointDirection(double x1, double y1, double x2, double y2)
    {
        double H = Math.sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1)); // The hypotenuse
        double x = x2-x1; // The opposite
        double y = y2-y1; // The adjacent
        double angle = Math.acos(x/H);
        angle = Math.toDegrees(angle);
        if(y < 0)
        {
            angle = 360-angle;
        }
        return angle;
    }

    private double pointDistance(double x1, double y1, double x2, double y2)
    {
        return Math.sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
    }


    public Rectangle headBound()
    {
        return segments.get(0).getBounds();
    }

    public void move(Main mainparent,boolean upkey,boolean leftkey, boolean rightkey)
    {

       move_head(mainparent,upkey,leftkey,rightkey);
       move_tail(mainparent);
       shake_world(mainparent);

       //Above Ground Setting//
       if(getHeadPosition().y < mainparent.getHeight()/2){
           //System.out.println("ABOVE GROUND");
           aboveGround = true;
       }else{
           aboveGround = false;
       }

    }

    public boolean getAboveGround(){
        return aboveGround;
    }

    private void shake_world(Main mainparent)
    {
        int head_x = getHeadPosition().x;
        int head_y = getHeadPosition().y;

        if(head_y < mainparent.getSize().height/2 && head_y > mainparent.getSize().height/2-shakemargin)
        {
            if(!mainparent.isShaking())
            {
                for(int i = 0; i < 50; i++)
                {
                     mainparent.addParticle(new Particle(head_x+segments.get(0).graphics.getWidth()/2,mainparent.getSize().getHeight()/2,new Color(127,55,0),4,2));
                }

                new AePlayWave("Sounds\\sndRumble.wav").start();
            }
             mainparent.setShaking(true);
        }
        else
        {
            mainparent.setShaking(false);
        }

    }
    private void move_head(Main mainparent,boolean upkey,boolean leftkey, boolean rightkey)
    {

        double head_direction = segments.get(0).direction;
        double head_speed = segments.get(0).speed;
        int head_x = segments.get(0).x;
        int head_y = segments.get(0).y;

        double head_y_speed;
        double head_x_speed;
        while(head_direction < 0)
        	head_direction += 360;
        while(head_direction > 360)
        	head_direction -= 360;


        if(head_y > mainparent.getSize().height/2)
        {
            if(leftkey)
                head_direction -= turn;
            if(rightkey)
                head_direction += turn;
            if(!upkey)
            {
                if(head_speed > speedMin)
                {
                    head_speed -= friction;
                }
            }
            else
            {
                head_speed += acceleration;
                if(head_speed > speedMax)
                    head_speed = speedMax;
            }
        }
        else
        {
            if(leftkey)
                head_direction -= slowturn;
            if(rightkey)
                head_direction += slowturn;

            head_y_speed = getYspeed(head_direction,head_speed) + gravity;
            head_x_speed = getXspeed(head_direction,head_speed);
            
            head_direction = calcYspeed(head_y_speed,head_x_speed);
        }

        head_x += getXspeed(head_direction,head_speed);
        head_y += getYspeed(head_direction,head_speed);


        if(head_x < 0)
            head_x = 0;
        if(head_x > mainparent.getMaxWidth() - segments.get(0).graphics.getWidth())
            head_x = mainparent.getMaxWidth() - segments.get(0).graphics.getWidth();
        if(head_y > mainparent.getHeight()-segments.get(0).graphics.getHeight())
            head_y = mainparent.getHeight()-segments.get(0).graphics.getHeight();

        segments.get(0).setInfo(head_x,head_y, head_direction, head_speed);
    }

    private void move_tail(Main mainparent)
    {
        int current_seg_x;
        int current_seg_y;
        int previous_seg_x;
        int previous_seg_y;
        double goDist;
        double goDir;
        double current_seg_speed;
        for(int x = 1;x<segments.size();x++)
        {
            current_seg_x = segments.get(x).x;
            current_seg_y = segments.get(x).y;
            current_seg_speed = segments.get(x).speed;
            previous_seg_x = segments.get(x-1).x;
            previous_seg_y = segments.get(x-1).y;

            goDist = pointDistance(current_seg_x,current_seg_y,previous_seg_x,previous_seg_y)-distance;
            goDir = pointDirection(current_seg_x,current_seg_y,previous_seg_x,previous_seg_y);


            current_seg_x += getXspeed(goDir,goDist);
            current_seg_y += getYspeed(goDir,goDist);

            if(current_seg_x < 0)
                current_seg_x = 0;
            if(current_seg_x > mainparent.getMaxWidth())
                current_seg_x = mainparent.getMaxWidth();
            if(current_seg_y > mainparent.getHeight())
                current_seg_y = mainparent.getHeight();

            segments.get(x).setInfo(current_seg_x,current_seg_y,goDir, current_seg_speed);
        }
    }

    public void draw(Graphics g,Main mainparent)
    {
        int shakeamount = mainparent.getShakeAmount();
        int move = mainparent.getSize().width/2;
        move -= mainparent.getScroll();

        int ymove = 0;

        if(mainparent.isShaking())
        {
            move += (random.nextInt(shakeamount*2)-shakeamount);
            ymove = (random.nextInt(shakeamount*2)-shakeamount);
        }

        for(int x = 0;x<segments.size();x++)
        {
            segments.get(x).draw(g, move, ymove);
        }

    }
    public int getXpos(){
        return segments.get(0).x;
    }

    public void setHP(int i) {
       this.hp = i;
    }
    
    public boolean getHit(){
        return hit;
    }
    public void resetHit(){
        hit = false;
    }

    public void setHit() {
        hit = true;
    }

    public void setEnemys(int e){

    }

}

class Worm_Segment
{
    DWGraphics graphics;
    int previous_x;
    int previous_y;
    double previous_direction;
    double previous_speed;
    int x;
    int y;
    double direction;
    double speed;

    public Worm_Segment(Image img, int x, int y)
    {
        graphics = new DWGraphics(img);
        speed = 5;
    }

    public Rectangle getBounds()
    {
        return graphics.bounds;
    }

    public void setInfo(int temp_x,int temp_y, double temp_direction,double temp_speed)
    {
        previous_x = x;
        previous_y = y;
        previous_direction = direction;
        previous_speed = speed;
        x = temp_x;
        y = temp_y;
        direction = temp_direction;
        speed = temp_speed;
    }
    public void draw(Graphics g,int move,int y_move)
    {
       graphics.draw(g,x+move,y+y_move,0, direction);
    }


}